package com.power.sifa.netlogin.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.aventrix.jnanoid.jnanoid.NanoIdUtils;
import com.plf.common.cache.redis.RedisCacheUtil;
import com.plf.common.domain.PageDataResponse;
import com.plf.common.domain.ResponseDTO;
import com.plf.common.utils.ExcelUtil;
import com.power.sifa.netlogin.api.INet_userFeign;
import com.power.sifa.netlogin.model.Net_user;
import com.power.sifa.netlogin.model.Net_userForm;
import com.power.sifa.netlogin.model.pageInfo.Net_userPageInfo;
import com.power.sifa.netlogin.model.pojo.vo.Net_userVO;
import com.power.sifa.netlogin.service.Net_userService;
import com.power.sifa.util.VerifyCodeUtil;
import com.power.sifa.util.service.impl.DidiSmsServiceImpl;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;


/**
 * 申诉端登录用户实体控制器
 */

@Slf4j
//@PowerLog
@RestController
@Api(value = "Net_userController", tags = {"申诉端登录用户实体"})
public class Net_userController implements INet_userFeign {

    @Resource
    private Net_userService net_userService;
    @Resource
    private RedisCacheUtil redisCacheUtil;

    /**
     * SM4 国密加密key
     */
    @Value("${power.config.SM4KEY:#{null}}")
    private String SM4KEY;

    private final static String REDIS_CODE_PREFIX = "NET_VERIFYCODE_";
    private final static String REDIS_CODE_ISALIVE = "NET_CODEISALIVE_";
    private final static String AUTHORIZATION = "Authorization";


    @Override
    @ApiOperation("查询申诉端登录用户实体分页列表")
    @SaCheckPermission("net_user_list")
    public ResponseDTO list(Net_userPageInfo pageInfo) {
        Assert.notNull(pageInfo, "pageInfo参数不能为空");
        Page<Net_user> page = this.net_userService.findAll(pageInfo);
        List list = new ArrayList();
        if (!page.isEmpty()) {
            for (Net_user net_user : page) {
                net_user.geneText();
                list.add(net_user);
            }
        }
        PageDataResponse p = new PageDataResponse(list, page.getTotalElements(), page.getSize(), pageInfo.getPageNumber() <= 1 ? 1 : pageInfo.getPageNumber());
        return ResponseDTO.succData(p);
    }

    @Override
    @ApiOperation("查看申诉端登录用户实体")
    @SaCheckPermission("net_user_view")
    public ResponseDTO view(String id) {
        Assert.notNull(id, "id不能为空");
        Net_user net_user = net_userService.getById(id);
        if (net_user != null) {
            net_user.geneText();
        }
        return ResponseDTO.succData(net_user);
    }

    @Override
    @ApiOperation("删除申诉端登录用户实体")
    @SaCheckPermission("net_user_del")
    public ResponseDTO delete(String id) {
        Assert.notNull(id, "id不能为空");
        net_userService.removeById(id);
        return ResponseDTO.succ();
    }

    @Override
    @ApiOperation("保存或修改申诉端登录用户实体")
    @SaCheckPermission("net_user_save")
    public ResponseDTO save(Net_user net_user) {
        Assert.notNull(net_user, "net_user不能为空");
        net_userService.saveOrUpdate(net_user);
        return ResponseDTO.succ();
    }

    @Override
    @ApiOperation(value = "批量删除申诉端登录用户实体")
    @SaCheckPermission("net_user_del")
    public ResponseDTO batchDel(String ids) {
        Assert.isTrue(StringUtils.hasText(ids), "ids不能为空");
        List<String> list = Arrays.asList(ids.split(",")).stream().map(s -> s.trim()).collect(Collectors.toList());
        net_userService.removeByIds(list);
        return ResponseDTO.succ();
    }

    @Override
    @ApiOperation(value = "导出excel")
    @SaCheckPermission("net_user_list")
    public void output(HttpServletResponse response, Net_userPageInfo pageInfo) {
        Assert.notNull(pageInfo, "pageInfo不能为空");
        String title = "申诉端登录用户实体";
        String[] heads = {"用户id", "用户名称", "用户全称", "身份证号", "密码", "性别", "身份证正面", "身份证国徽面", "头像", "电话", "邮件", "删除标志", "过期时间"};
        String[] fields = {"userid", "username", "fullname", "cardno", "password", "gender", "cardfront", "cardback", "avatar", "phone", "email", "deleted", "expiredate"};
        Page<Net_user> page = this.net_userService.findAll(pageInfo);
        ExcelUtil.exportXls(title, heads, fields, page.getContent(), response);
    }

    @Override
    @ApiOperation(value = "导出excel模板")
    public void exportExcelTemplate(HttpServletResponse response) {
        String title = "申诉端登录用户实体";
        //id自增或list从表可自行删除，需与导入项一致
        String[] heads = {"用户id", "用户名称", "用户全称", "身份证号", "密码", "性别", "身份证正面", "身份证国徽面", "头像", "电话", "邮件", "删除标志", "过期时间"};
        ExcelUtil.exportXls(title, heads, null, null, response);
    }

    @Override
    @ApiOperation(value = "导入excel")
    public ResponseDTO importExcel(MultipartFile file) throws IOException {
        Assert.notNull(file, "file不能为空");
        //id自增或list从表可自行删除，需与下载的模板中导入项一致
        String[] fields = {"userid", "username", "fullname", "cardno", "password", "gender", "cardfront", "cardback", "avatar", "phone", "email", "deleted", "expiredate"};
        List<Net_user> list = (List<Net_user>) ExcelUtil.Import(fields, file, Net_user.class);
        if (!CollectionUtils.isEmpty(list)) {
            this.net_userService.saveAll(list);
        }
        return ResponseDTO.succ();
    }

    @Override
    @ApiOperation(value = "网申端登录")
    public ResponseDTO doLogin(String phone, String password, HttpServletResponse response) {
        Assert.notNull(phone, "登录电话号码不能为空");
        Assert.notNull(password, "password不能为空");

        // 查询是否有账号
        Net_user user = this.net_userService.getByPhone(phone);
        if (ObjectUtil.isNull(user)) {
            return ResponseDTO.succData(new ResponseDTO(-100, "当前号码未注册，请先注册再登录"), "接口成功");
        }
        // 判断账密是否一致
        if (!password.equals(user.getPassword())) {
            return ResponseDTO.succData(new ResponseDTO(-100, "当前密码错误，请重新输入"), "接口成功");
        } else {
            // saToken 登录
            StpUtil.login(user.getUserid());
            response.setHeader("Access-Control-Expose-Headers", AUTHORIZATION);
            response.addHeader(AUTHORIZATION, StpUtil.getTokenValue());
            return ResponseDTO.succData(new ResponseDTO(0, user, "登录成功"), "登录成功");
        }
    }

    @Override
    @ApiOperation(value = "网申端获取验证码")
    public ResponseDTO getVerificationCode(String phone) {
        Assert.notNull(phone, "电话号码不能为空");
        try {
            // 判断号码是否存在
            Net_user user = this.net_userService.getByPhone(phone);
            if (ObjectUtil.isNotNull(user)) {
                return ResponseDTO.succData(new ResponseDTO(-100, "当前号码已注册"), "接口成功");
            }
            // 判断是否存在一分钟内的验证码
            final String isAliveKey = REDIS_CODE_ISALIVE + phone;
            final Boolean isAlive = (Boolean) redisCacheUtil.get(isAliveKey);
            if (ObjectUtil.isNotNull(isAlive) && isAlive) {
                return ResponseDTO.succData(new ResponseDTO(-100, "当前号码一分钟已发送验证码，请勿重复发送"), "接口成功");
            }
            // 生成六位验证码，有效时间5分钟
            String code = VerifyCodeUtil.generateCode(6);
            // 调用发送短信
            DidiSmsServiceImpl bean = new DidiSmsServiceImpl();
            List<String> list = new ArrayList<>();
            list.add(code);
            bean.sendTemplate(DidiSmsServiceImpl.tpl_vericode, list, phone);

            // 当前验证码发送计时一分钟，避免多次发送
            redisCacheUtil.set(isAliveKey, true, 1 * 60L);

            // 发送成功后 记录到redis中，有效期为5分钟
            final String key = REDIS_CODE_PREFIX + phone;
            redisCacheUtil.set(key, code, 5 * 60L);
            return ResponseDTO.succData(new ResponseDTO(0, "发送验证码成功"), "发送验证码成功");
        } catch (Exception e) {
            e.printStackTrace();
            log.error("用户:{}注册发送验证码异常:{}", phone, e.getMessage());
        }
        return ResponseDTO.succData(new ResponseDTO(-100, "发送验证码失败"), "接口成功");
    }

    @Override
    @ApiOperation(value = "网申端注册用户")
    public ResponseDTO registerUser(Net_userForm userForm) {
        Assert.notNull(userForm, "注册表单不能为空");
        Assert.notNull(userForm.getPhone(), "注册电话号码不能为空");

        try {
            // 判断当前用户的验证码是否和redis保存的一致
            final String key = REDIS_CODE_PREFIX + userForm.getPhone();
            final String verifyCode = (String) redisCacheUtil.get(key);
            if (org.apache.commons.lang3.StringUtils.isEmpty(verifyCode)) {
                return ResponseDTO.succData(new ResponseDTO(-100, "请输入验证码"), "接口成功");
            }
            if (!verifyCode.equals(userForm.getVerifyCode())) {
                return ResponseDTO.succData(new ResponseDTO(-100, "输入的验证码有误"), "接口成功");
            }
            // 查询是否存在用户
            Net_user dbUser = this.net_userService.getByPhone(userForm.getPhone());
            if (ObjectUtil.isNotNull(dbUser)) {
                return ResponseDTO.succData(new ResponseDTO(-100, "号码已注册请登录"), "接口成功");
            }
            // 保存用户
            Net_user user = BeanUtil.toBean(userForm, Net_user.class);
            user.setUserid(NanoIdUtils.randomNanoId());
            this.net_userService.saveOrUpdate(user);
            return ResponseDTO.succData(new ResponseDTO(0, "注册成功"), "注册成功");
        } catch (Exception e) {
            e.printStackTrace();
            log.error("用户:{}注册异常:{}", userForm.getPhone(), e.getMessage());
        }
        return ResponseDTO.succData(new ResponseDTO(-100, "注册失败"), "注册失败");

    }

    @Override
    @ApiOperation(value = "网申端认证用户")
    public ResponseDTO authenticateUser(Net_userForm userForm) {
        Assert.notNull(userForm, "认证表单不能为空");
        Assert.notNull(userForm.getPhone(), "认证电话号码不能为空");
        try {
            // 查询当前的用户
            Net_user dbUser = this.net_userService.getByPhone(userForm.getPhone());
            if (ObjectUtil.isNull(dbUser)) {
                return ResponseDTO.succData(new ResponseDTO(-100, "当前用户不存在，无法认证"), "接口成功");
            } else {
                // 保存对应信息
                BeanUtil.copyProperties(userForm, dbUser, "userid", "password", "phone");
                // 保存用户
                this.net_userService.saveOrUpdate(dbUser);
                return ResponseDTO.succData(new ResponseDTO(0, dbUser), "认证成功");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("用户:{}认证异常:{}", userForm.getPhone(), e.getMessage());
        }
        return ResponseDTO.succData(new ResponseDTO(-100, "认证失败"), "接口成功");

    }

    @Override
    @ApiOperation(value = "网申端登出")
    public ResponseDTO logout() {
        StpUtil.logout();
        return ResponseDTO.succMsg("登出成功");
    }

    @Override
    public ResponseDTO isLogin() {
        return ResponseDTO.succData(StpUtil.isLogin());
    }

    @Override
    public ResponseDTO getUserInfo(String userid) {
        Assert.notNull(userid, "userid不能为空");
        Net_user user = this.net_userService.getById(userid);
        if (ObjectUtil.isNotNull(user)) {
            return ResponseDTO.succData(BeanUtil.toBean(user, Net_userVO.class));
        }
        return ResponseDTO.succData(500,"查询用户信息异常");
    }

}
